package cn.hubujyjs.lp.service.impl;


import cn.hubujyjs.lp.bo.UpdateUserBo;
import cn.hubujyjs.lp.bo.UserBo;
import cn.hubujyjs.lp.config.UserHolder;
import cn.hubujyjs.lp.service.MailService;
import cn.hubujyjs.lp.utils.R;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.hubujyjs.lp.domain.User;
import cn.hubujyjs.lp.service.UserService;
import cn.hubujyjs.lp.mapper.UserMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import static cn.hubujyjs.lp.constant.Constants.USER_NAME_PREFIX;
import static cn.hubujyjs.lp.constant.RedisConst.*;

/**
* @author admin
* @description 针对表【user】的数据库操作Service实现
* @createDate 2023-05-15 18:24:28
*/
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
    implements UserService{

    @Autowired
    private MailService mailService;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    public static final ExecutorService sendMailThread= Executors.newFixedThreadPool(10);
    /**
     * 登录
     * @param email 邮箱
     * @param verificationCode 验证码
     * @return 成功返回token
     */
    @Override
    public R<String> login(String email, String verificationCode) {
        User user;
        //验证码登录
        if (StrUtil.isNotBlank(verificationCode)){
            String s = stringRedisTemplate.opsForValue().get(PL_EMAIL_KEY_ + email);
            if (s == null || !s.equals(verificationCode)) {
                return R.fail("验证码错误或验证码已过期");
            }
            //查询用户
            user = getUser(email);
            //用户不存在，注册
            if (user==null){
                user = createUserWithPhone(email);
            }
        }else {
            return R.fail("请求参数错误");
        }
        //保存用户信息到 redis中
        String token = UUID.randomUUID().toString(true);
        UserBo userBo = BeanUtil.copyProperties(user, UserBo.class);
        Map<String, Object> map = BeanUtil.beanToMap(userBo);
        map.replaceAll((k, v) -> String.valueOf(v));

        String tokenKey = PL_USER_KEY_ + token;
        stringRedisTemplate.opsForHash().putAll(tokenKey, map);
        //设置token有效期
        stringRedisTemplate.expire(tokenKey, LOGIN_USER_TTL, TimeUnit.DAYS);

        return R.ok(token);
    }

    /**
     * 发送验证码
     * @param email 邮箱
     * @return null
     */
    @Override
    public R<Object> code(String email) {
        if (StringUtils.hasText(email)){
            //生成验证码
            String s = RandomUtil.randomNumbers(4);
            sendMailThread.submit(()->{
                mailService.sendSimpleMail(email,"学习平台邮箱验证码","您的验证码是:"+s+"。5分钟内有效!");
            });
            stringRedisTemplate.opsForValue()
                    .set(PL_EMAIL_KEY_+email, s,PL_EMAIL_TTL, TimeUnit.MINUTES);
        }
        return R.ok();
    }

    /**
     * 用户信息查询
     * @return Usser
     */
    @Override
    public R<User> info() {
        Long id = UserHolder.getUser().getId();
        User user = this.getById(id);
        return R.ok(user);
    }

    /**
     * 更新用户信息
     * @param updateUserBo 用户信息业务对象
     * @return null
     */
    @Override
    public R<Object> updateUser(UpdateUserBo updateUserBo) {
        Long id = UserHolder.getUser().getId();
        User user = new User();
        user.setId(Math.toIntExact(id));
        user.setName(updateUserBo.getName());
        user.setPicture(updateUserBo.getPicture());
        this.updateById(user);
        return R.ok();
    }

    /**
     * 退出登录
     * @param request Request请求
     * @return null
     */
    @Override
    public R<Object> logout(HttpServletRequest request) {
        String header = request.getHeader("X-Token");
        String token=PL_USER_KEY_ + header;
        stringRedisTemplate.delete(token);
        return R.ok();
    }

    /**
     * 根据邮箱地址查询用户
     * @param email 邮箱
     * @return 用户
     */
    private User getUser(String email) {
        LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(User::getEmail, email);
        return this.getOne(wrapper);
    }

    /**
     * 注册
     * @param email 邮箱
     * @return 用户
     */
    private User createUserWithPhone(String email) {
        User user=new User();
        user.setEmail(email);
        //设置随机用户名
        user.setName(USER_NAME_PREFIX+RandomUtil.randomString(6));
        user.setPicture("https://hjtblogpic.oss-cn-shanghai.aliyuncs.com/mirai/2023/02/04/8ae9970f7e2d41faa8dcba4995798ecb.jpg");
        this.save(user);
        return user;
    }
}




